﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace Reactor.Messaging.ServiceBus
{
    /// <summary>
    /// Interface defining the operations available on an implementation of a message handler registry. Such registries 
    /// discover and store mappings between message handlers and the message types they handle.
    /// </summary>
    public interface IHandlerRegistry
    {
        /// <summary>
        /// Occurs when message handlers are registered.
        /// </summary>
        event EventHandler<HandlersRegisteredEventArgs> HandlersRegistered;

        /// <summary>
        /// Compiles a list of all assemblies loaded into the current AppDomain, removes predetermined 
        /// assemblies known to not contain message handlers, and forwards the final list to the ScanAssembliesForHandlers 
        /// overload that takes an enumerable list of assemblies.
        /// </summary>
        void ScanAssembliesForHandlers();

        /// <summary>
        /// Scans the assemblies for handlers.
        /// </summary>
        /// <param name="assemblies">The assemblies.</param>
        void ScanAssembliesForHandlers(IEnumerable<Assembly> assemblies);

        /// <summary>
        /// Manually registers the type of the message handler. This method is useful 
        /// for handlers that have dynamic destinations bound to it at runtime, rather 
        /// than static subscription declarations in the form of attributes.
        /// </summary>
        /// <param name="messageHandlerType">Type of the message handler.</param>
        /// <param name="expectedDestinations">The expected destinations.</param>
        void RegisterMessageHandlerType(Type messageHandlerType, IList<IMessagingChannel> expectedDestinations);

        /// <summary>
        /// Gets all message handler registrations.
        /// </summary>
        /// <returns></returns>
        IEnumerable<MessageHandlerRegistration> GetAllHandlerRegistrations();

        /// <summary>
        /// Gets all types that handle the specified message type.
        /// </summary>
        /// <typeparam name="T">Message Type</typeparam>
        /// <returns>List of types that handle the specified message type.</returns>
        IList<Type> GetHandlerTypesForMessageType<T>() where T : class;

        /// <summary>
        /// Gets all types that handle the specified message type.
        /// </summary>
        /// <param name="messageType">Message Type</param>
        /// <returns>List of types that handle the specified message type.</returns>
        IList<Type> GetHandlerTypesForMessageType(Type messageType);

        /// <summary>
        /// Gets all handler types contained in the provided assemblies.
        /// </summary>
        /// <param name="assemblies">The assemblies.</param>
        /// <returns></returns>
        IList<Type> GetHandlerTypesContainedInAssemblies(IEnumerable<Assembly> assemblies);
    }

    public class HandlersRegisteredEventArgs : EventArgs
    {
        /// <summary>
        /// Gets or sets the registrations.
        /// </summary>
        /// <value>The registrations.</value>
        public IEnumerable<MessageHandlerRegistration> Registrations { get; set;}
    }
}
